home *** CD-ROM | disk | FTP | other *** search
- /* << ACE >>
-
- -- Amiga BASIC Compiler --
-
- ** Lexical Analyser **
- ** Copyright (C) 1998 David Benn
- **
- ** This program is free software; you can redistribute it and/or
- ** modify it under the terms of the GNU General Public License
- ** as published by the Free Software Foundation; either version 2
- ** of the License, or (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- Author: David J Benn
- Date: 18th October-30th November, 1st-13th December 1991,
- 14th,20th,26th January 1992,
- 2nd-17th, 23rd-24th February 1992,
- 21st April 1992,
- 7th,11th,13th June 1992,
- 2nd,3rd,4th,5th,8th,14th,15th,16th,19th,26th,28th,29th July 1992,
- 2nd,8th August 1992,
- 6th,22nd,27th-30th December 1992,
- 4th,5th,7th,19th,31st January 1993,
- 2nd,6th,11th-15th,19th,28th February 1993,
- 1st,24th March 1993,
- 12th,17th April 1993,
- 6th,13th June 1993,
- 1st,2nd,10th July 1993,
- 5th,26th September 1993,
- 15th November 1993,
- 14th,16th,17th,25th,26th December 1993,
- 2nd,5th,7th-9th January 1994,
- 7th,15th February 1994,
- 20th,22nd,28th August 1994,
- 4th,10th,11th September 1994,
- 7th August 1995,
- 6th October 1995,
- 10th March 1996,
- 11th June 1996,
- 4th September 1996
- */
-
- #include "lexvar.h"
- #include <string.h>
- #include <clib/exec_protos.h>
- #include <clib/mathffp_protos.h>
- #include <clib/mathtrans_protos.h>
- #include <stdlib.h>
-
- /* globals */
-
- struct Library *MathBase = NULL;
- struct Library *MathTransBase = NULL;
- struct IntuitionBase *IntuitionBase = NULL;
-
-
- BOOL inside_string = FALSE; /* see last line of nextch() */
-
- /* functions */
- void open_shared_libs (void)
- {
- if ((MathBase = (struct Library *) OpenLibrary ("mathffp.library", 0)) == NULL)
- {
- printf ("Unable to open mathffp.library!\n");
- exit (10);
- }
-
- if ((MathTransBase = (struct Library *) OpenLibrary ("mathtrans.library", 0)) == NULL)
- {
- printf ("Unable to open mathtrans.library!\n");
- exit (10);
- }
-
- if ((IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 0)) == NULL)
- {
- printf ("Unable to open intuition.library!\n");
- exit (10);
- }
- }
-
- void close_shared_libs (void)
- {
- if (IntuitionBase != NULL)
- CloseLibrary ((struct Library *) MathTransBase);
- if (MathTransBase != NULL)
- CloseLibrary ((struct Library *) MathTransBase);
- if (MathBase != NULL)
- CloseLibrary ((struct Library *) MathBase);
- }
-
- void setup (void)
- {
- int i;
-
- /* initialize nextch() variables */
- column = linelen = -1;
- line[0] = '\0';
-
- /*
- ** All id's default to singletype (A..Z + "_"
- ** with 4 bytes wasted between Z and "_").
- */
- for (i = 0; i <= 30; i++)
- idtype[i] = singletype;
-
- /* libraries used by ACE */
- strcpy (acelib[0].name, "DOS");
- strcpy (acelib[0].base, "_DOSBase");
- strcpy (acelib[1].name, "INTUITION");
- strcpy (acelib[1].base, "_IntuitionBase");
- strcpy (acelib[2].name, "GRAPHICS");
- strcpy (acelib[2].base, "_GfxBase");
- strcpy (acelib[3].name, "MATHFFP");
- strcpy (acelib[3].base, "_MathBase");
- strcpy (acelib[4].name, "MATHTRANS");
- strcpy (acelib[4].base, "_MathTransBase");
- strcpy (acelib[5].name, "TRANSLATOR");
- strcpy (acelib[5].base, "_TransBase");
- /* sentinel ACE library entry */
- strcpy (acelib[6].name, "SENTINEL");
-
- /* make "other library" entries null */
- for (i = 0; i < NUMLIBS - 1; i++)
- {
- otherlib[i].name[0] = '\0';
- otherlib[i].base[0] = '\0';
- }
- /* sentinel for "other libraries" */
- strcpy (otherlib[NUMLIBS - 1].name, "SENTINEL");
-
- /* open error log? */
- if (error_log)
- {
- err_log = fopen ("ace.err", "w");
- if (err_log == NULL)
- {
- puts ("Unable to open error log: ace.err!");
- exit (10);
- }
- }
- }
-
- void cleanup (void)
- {
- /* close files */
- if (!std_in && src != NULL)
- fclose (src);
- if (dest != NULL)
- fclose (dest);
- if (err_log != NULL)
- fclose (err_log);
-
- free_alloc ();
-
- close_shared_libs ();
-
- /* exit with return value */
- if (early_exit)
- exitvalue = 10;
- exit (exitvalue);
- }
-
- void _warn (int n)
- {
- char *msg;
-
- printf ("Warning: ");
- if (error_log)
- fprintf (err_log, "Warning: ");
-
- switch (n)
- {
- case 0: /* dummy */
- break;
- case 1:
- msg = "Exponent out of range";
- break;
- }
- printf ("%s", msg);
- if (error_log)
- fprintf (err_log, "%s", msg);
- printf (" in line %d.\n", lineno);
- if (error_log)
- fprintf (err_log, " in line %d.\n", lineno);
- }
-
- void _error (int n)
- {
- int i, spot, badline, length;
- char *msg;
-
- /* display an error and the line in which it occurs */
-
- if (!report_errors)
- return; /* eg. see assem() in misc.c */
-
- if (n > 1 && n != 8)
- {
- if (n != 12 && n != 15 && n != 17 && n != 25 && n != 34 &&
- n != 51 && n != 52 && n != 64 && n != 73)
- {
- /* show the offending line */
- if (column != 0)
- {
- length = strlen (line);
- if (length > 0)
- {
- printf ("\n%s\n", line);
- if (error_log)
- fprintf (err_log, "\n%s\n", line);
- spot = column;
- }
- badline = lineno;
- }
- else
- {
- length = strlen (lastline);
- if (length > 0)
- {
- printf ("\n%s\n", lastline);
- if (error_log)
- fprintf (err_log, "\n%s\n", lastline);
- spot = length;
- }
- badline = lineno - 1;
- }
-
- if (length > 0)
- {
- /* point to the error */
- for (i = 1; i < spot; i++)
- {
- putchar (' ');
- if (error_log)
- fputc (' ', err_log);
- }
- printf ("^\n");
- if (error_log)
- fprintf (err_log, "^\n");
- }
-
- /* ignore rest of line */
- column = linelen;
- ch = ' '; /* force a call to nextch() when insymbol() next invoked */
- }
- else
- {
- putchar ('\n');
- if (error_log)
- fputc ('\n', err_log);
- badline = lineno;
- }
-
- printf ("** ");
- if (error_log)
- fprintf (err_log, "** ");
-
- if (!early_exit)
- early_exit = TRUE;
- }
-
- switch (n)
- {
- case 0: /* dummy */
- break;
- case 1:
- msg = "Unexpected end of source\n";
- break;
- case 2:
- msg = "Unknown symbol";
- break;
- case 3:
- msg = "Decimal digit expected";
- break;
- case 4:
- msg = "Type mismatch";
- break;
- case 5:
- msg = "'=' expected";
- break;
- case 6:
- msg = "Duplicate label";
- break;
- case 7:
- msg = "Identifier expected";
- break;
- case 8:
- msg = "\nUndefined label: ";
- break;
- case 9:
- msg = "')' expected";
- break;
- case 10:
- msg = "Expression expected";
- break;
- case 11:
- msg = "IF without THEN";
- break;
- case 12:
- msg = "WHILE without WEND";
- break;
- case 13:
- msg = "Illegal expression";
- break;
- case 14:
- msg = "'(' expected";
- break;
- case 15:
- msg = "IF without END IF";
- break;
- case 16:
- msg = "',' expected";
- break;
- case 17:
- msg = "FOR without NEXT";
- break;
- case 18:
- msg = "String constant expected";
- break;
- case 19:
- msg = "Variable expected";
- break;
- case 20:
- msg = "'b' or 'bf' expected";
- break;
- case 21:
- msg = "'-' expected";
- break;
- case 22:
- msg = "Array already dimensioned";
- break;
- case 23:
- msg = "Illegal array index";
- break;
- case 24:
- msg = "Illegal use of identifier";
- break;
- case 25:
- msg = "READ without DATA";
- break;
- case 26:
- msg = "Constant expected";
- break;
- case 27:
- msg = "Numeric constant expected";
- break;
- case 28:
- msg = "Short integer array expected";
- break;
- case 29:
- msg = "Radius expected";
- break;
- case 30:
- msg = "No start angle specified";
- break;
- case 31:
- msg = "Illegal letter-range";
- break;
- case 32:
- msg = "Subprogram name expected";
- break;
- case 33:
- msg = "Duplicate subprogram/function name";
- break;
- case 34:
- msg = "SUB without END SUB";
- break;
- case 35:
- msg = "SUB expected";
- break;
- case 36:
- msg = "EXIT SUB illegal outside subprogram";
- break;
- case 37:
- msg = "CALL to undeclared subprogram";
- break;
- case 38:
- msg = "Parameter already declared";
- break;
- case 39:
- msg = "Parameter count mismatch";
- break;
- case 40:
- msg = "Object cannot be shared";
- break;
- case 41:
- msg = "Zero or negative string size";
- break;
- case 42:
- msg = "Too many parameters in SUB";
- break;
- case 43:
- msg = "Invalid object";
- break;
- case 44:
- msg = "'#' expected";
- break;
- case 45:
- msg = "Library already open";
- break;
- case 46:
- msg = "Library not open";
- break;
- case 47:
- msg = "FUNCTION expected";
- break;
- case 48:
- msg = "LIBRARY expected";
- break;
- case 49:
- msg = "Unknown library function";
- break;
- case 50:
- msg = "Can't open bmap file";
- break;
- case 51:
- msg = "REPEAT without UNTIL";
- break;
- case 52:
- msg = "CASE without END CASE";
- break;
- case 53:
- msg = "Unable to reassign a constant";
- break;
- case 54:
- msg = "Variable exists";
- break;
- case 55:
- msg = "Event specifier expected";
- break;
- case 56:
- msg = "GOSUB, GOTO or CALL expected";
- break;
- case 57:
- msg = "Label, line number or SUB name expected";
- break;
- case 58:
- msg = "ON, OFF or STOP expected";
- break;
- case 59:
- msg = "No event trapping label or SUB defined for this event";
- break;
- case 60:
- msg = "Identifier or Type expected";
- break;
- case 61:
- msg = "Duplicate structure member";
- break;
- case 62:
- msg = "Structure type already defined";
- break;
- case 63:
- msg = "Member type declaration expected";
- break;
- case 64:
- msg = "STRUCT without END STRUCT";
- break;
- case 65:
- msg = "Unknown structure type";
- break;
- case 66:
- msg = "Structure already declared";
- break;
- case 67:
- msg = "Not a structure member";
- break;
- case 68:
- msg = "Unrecognised or incorrectly used command/function";
- break;
- case 69:
- msg = "SHARED can only be used inside a subprogram";
- break;
- case 70:
- msg = "FOR loop index cannot be a shared variable";
- break;
- case 71:
- msg = "Undefined function or array not dimensioned";
- break;
- case 72:
- msg = "AS expected";
- break;
- case 73:
- msg = "ASSEM without END ASSEM";
- break;
- case 74:
- msg = "Compiler directive expected";
- break;
- case 75:
- msg = "OPEN, CLOSE, READ, WRITE or NAME expected";
- break;
- case 76:
- msg = "Unable to open another library";
- break;
- case 77:
- msg = "OPEN, CLOSE, READ, WRITE, WAIT or CLEAR expected";
- break;
- case 78:
- msg = "An event trapping SUB may not have a parameter list";
- break;
- case 79:
- msg = "Structure variable expected";
- break;
- case 80:
- msg = "BLOCK without END BLOCK";
- break;
- }
-
- /* show the error */
- printf ("%s", msg);
- if (error_log)
- fprintf (err_log, "%s", msg);
- if (n > 1 && n != 8)
- {
- printf (" in line %d.\n", badline);
- if (error_log)
- fprintf (err_log, " in line %d.\n", badline);
- }
-
- if (n != 0)
- errors++;
- }
-
- void _abort (int n)
- {
- _error (n);
- printf ("*** compilation aborted with %d error(s).\n", errors);
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- void open_files (char *source)
- {
- int cc;
- char *xtn;
-
- /*
- ** Open source file: allocate memory for extension in case required.
- */
- srcfile = (char *) alloc (strlen (source) + 3, MEMF_ANY); /* 3 = 2*Xtn + EOS */
- if (srcfile == NULL)
- {
- puts ("can't allocate memory for source file name.");
- early_exit = TRUE;
- cleanup ();
- }
-
- /* copy source file name */
- strcpy (srcfile, source);
-
- /*
- ** Does source file name already have an extension (.b or .bas)?
- ** If not, add one.
- */
- cc = 0;
- while (srcfile[cc] && srcfile[cc] != '.')
- cc++;
-
- xtn = &srcfile[cc];
-
- /*
- ** Allow an extension of ".bas",".BAS",
- ** ".b" or ".B". If none is present -> append ".b".
- */
- if (strcmp (xtn, ".bas") != 0 && strcmp (xtn, ".BAS") != 0 &&
- strcmp (xtn, ".b") != 0 && strcmp (xtn, ".B") != 0)
- strcat (srcfile, ".b");
-
- /* open source file */
- if ((src = fopen (srcfile, "r")) == NULL)
- {
- printf ("can't open %s.\n", srcfile);
- early_exit = TRUE;
- cleanup ();
- }
-
- /*
- ** Open object file.
- */
- destfile = (char *) alloc (strlen (srcfile) + 1, MEMF_ANY);
- if (destfile == NULL)
- {
- puts ("can't allocate memory for object file name.");
- early_exit = TRUE;
- cleanup ();
- }
-
- /* copy source file name and change extension to ".s" */
- cc = 0;
- while (srcfile[cc] != '.')
- {
- destfile[cc] = srcfile[cc];
- cc++;
- }
- destfile[cc] = '\0';
- strcat (destfile, ".s");
-
- /* open target file */
- if ((dest = fopen (destfile, "w")) == NULL)
- {
- printf ("can't write to %s.\n", destfile);
- early_exit = TRUE;
- cleanup ();
- }
- }
-
- void nextch (void)
- /* character handler */
- {
- char lineno_buf[15], *tmp;
- int i;
- long n;
-
- /* if user hits ctrl-c clean up and abort. */
- if (SetSignal (0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
- {
- puts ("\n*** Break: ACE terminating.");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- if (column == linelen)
- {
- strcpy (lastline, line);
-
- /* refill line buffer */
- column = linelen = -1;
-
- do
- {
- line[++linelen] = (ch = getc (src));
- }
- while ((ch != '\n') && (ch != EOF) && (linelen < MAXLINELEN));
-
- /* next line of source code */
- line[linelen] = '\0';
-
- /*
- ** !!! eoln for previous line [PRINT statement etc] !!!
- **
- ** Having just refilled the line buffer means we've
- ** run out of characters, so reached the eoln. The last
- ** character was '\0' which will be treated as whitespace
- ** but which is required for string literal parsing.
- **
- ** If the previous line's last non-whitespace character is '~' the line
- ** should be continued (ie. the eoln should be ignored) and the '~'
- ** character should be seen as whitespace.
- **
- ** Geez this whole EOLN thing is _messy_!!
- */
- tmp = lastline;
- while (*tmp)
- tmp++; /* find EOS */
- while (tmp > lastline && *tmp <= ' ')
- tmp--; /* find '~' */
- if (*tmp != '~')
- sym = endofline;
-
- /* advance line counter */
- lineno++;
-
- /*
- ** Check for EOF -> Due to some editors, last line may not have
- ** a LF, but parse it! Next time nextch() is called
- ** EOF will be detected immediately.
- */
- if (ch == EOF && linelen == 0)
- {
- if ((lineno == 0) && (linelen == 0))
- _abort (1);
- else
- end_of_source = TRUE;
- }
-
- /* line count display */
- if (!list_source && ((lineno % 10 == 0) || end_of_source))
- {
- n = lineno;
- if (end_of_source && linelen == 0)
- --n;
- printf ("\rCompiling line %s", itoa (n, lineno_buf, 10));
- for (i = 1; i <= strlen (lineno_buf); i++)
- putchar ('\b');
- fflush (stdout);
- }
-
- if (!end_of_source)
- {
- /* use source code line as a comment? */
- if (asm_comments)
- gen ("; *** ", line, " ");
-
- /* show each source code line before compilation? */
- if (list_source)
- printf ("%ld: %s\n", lineno, line);
- }
- }
-
- /* next character */
- column++;
- ut_ch = ch = line[column];
- if (ch == '~' && !inside_string)
- ut_ch = ch = ' '; /* '~' == whitespace */
- }
-
- BOOL letter (void)
- {
- if ((ch >= 'A') && (ch <= 'Z'))
- return (TRUE);
- if ((ch >= 'a') && (ch <= 'z'))
- {
- ch -= 32;
- return (TRUE);
- }
- return (FALSE);
- }
-
- BOOL digit (void)
- {
- if ((ch >= '0') && (ch <= '9'))
- return (TRUE);
- else
- return (FALSE);
- }
-
- int hex_digit (void)
- {
- if ((ch >= '0') && (ch <= '9'))
- return (ch - '0');
- letter (); /* make sure it's uppercase */
- if ((ch >= 'A') && (ch <= 'F'))
- return (10 + ch - 'A');
- return (-1);
- }
-
- int octal_digit (void)
- {
- if ((ch >= '0') && (ch <= '7'))
- return (ch - '0');
- return (-1);
- }
-
- void convert_special_ident (void)
- {
- /*
- ** If the current identifier is one of a special
- ** group, modify it by prefixing an underscore.
- **
- ** This is a kludge to get around problems with
- ** certain names (eg: 68000 register names)
- ** which cause A68K to generate errors when
- ** encountered as labels.
- */
- char chr0, chr1;
-
- chr0 = id[0];
- chr1 = id[1];
-
- /*
- ** Address or data register name? (A0..A7, D0..D7 or SP)
- ** If so -> convert to _Dn, _An or _SP.
- */
- if (((chr0 == 'A' || chr0 == 'D') &&
- (chr1 >= '0' && chr1 <= '7' && id[2] == '\0')) ||
- (chr0 == 'S' && chr1 == 'P' && id[2] == '\0'))
- {
- /* convert id */
- id[3] = '\0';
- id[2] = chr1;
- id[1] = chr0;
- id[0] = '_';
- }
- }
-
- BOOL qualifier (void)
- {
- /* - Attach a qualifier character (%&$!#).
- - The default object (variable) can be overriden by
- the later declaration of an array, subprogram etc.
- */
-
- switch (ch)
- {
- case '$':
- obj = variable;
- typ = stringtype;
- return (TRUE);
- case '%':
- obj = variable;
- typ = shorttype;
- return (TRUE);
- case '&':
- obj = variable;
- typ = longtype;
- return (TRUE);
- case '!':
- obj = variable;
- typ = singletype;
- return (TRUE);
- case '#':
- obj = variable;
- typ = singletype;
- return (TRUE);
- default:
- obj = undefined;
- typ = undefined;
- return (FALSE);
- }
- }
-
- BOOL ssymbol (void)
- {
- int i = 0;
- BOOL found = FALSE;
-
- /* if (ch == '"') return(TRUE); */
- while ((spec_sym[i] != '\0') && (!found))
- if (ch == spec_sym[i++])
- found = TRUE;
- return (found);
- }
-
- int rsvd_wd (char *id)
- {
- BOOL found = FALSE;
- int first, last, this;
-
- /* search the reserved word
- list using a binary search
- for AmigaBASIC and then ACE
- keywords.
- */
-
- /* AmigaBASIC keyword? */
- first = abssym;
- last = xorsym;
- do
- {
- this = (first + last) / 2;
- if (strcmp (id, rword[this]) <= 0)
- last = this - 1; /* id <= rword[this] ? */
- if (strcmp (id, rword[this]) >= 0)
- first = this + 1; /* id >= rword[this] ? */
- }
- while (first <= last);
- if (first - 1 > last)
- found = TRUE;
-
- /* ACE keyword? */
- if (!found)
- {
- first = addresssym;
- last = ycorsym;
- do
- {
- this = (first + last) / 2;
- if (strcmp (id, rword[this]) <= 0)
- last = this - 1; /* id <= rword[this] ? */
- if (strcmp (id, rword[this]) >= 0)
- first = this + 1; /* id >= rword[this] ? */
- }
- while (first <= last);
- if (first - 1 > last)
- found = TRUE;
- }
-
- if (found)
- return (this);
- else
- return (undefined);
- }
-
- int rsvd_sym (char *id)
- {
- BOOL found = FALSE;
- int cc = 0;
-
- /* reserved symbol? */
- do
- {
- if (strcmp (id, rsym[cc++]) == 0)
- found = TRUE;
- }
- while ((!found) && (strcmp (rsym[cc], "SENTINEL") != 0));
- if (found)
- return (500 + cc - 1);
- else
- return (undefined);
- }
-
- void reclassify_number (void)
- {
- /* reclassify a number as a short, long or floating point value
- if a qualifying character (%&!#) follows the numeric literal.
- */
- if (ch == '%')
- {
- /* coerce to a SHORT constant */
- nextch ();
- switch (typ)
- {
- case longtype:
- shortval = (SHORT) longval;
- break;
- case singletype:
- if (SPCmp (0.5, SPSub (SPFloor (singleval), singleval)) == 1)
- shortval = (SHORT) SPFix (SPFloor (singleval));
- else
- shortval = (SHORT) SPFix (SPCeil (singleval));
- break; /*if fnum-fix(fnum)<0.5 round_down else round_up */
- }
- sym = shortconst;
- typ = shorttype;
- }
- else if (ch == '&')
- {
- /* coerce to a LONG constant */
- nextch ();
- switch (typ)
- {
- case shorttype:
- longval = (LONG) shortval;
- break;
- case singletype:
- if (SPCmp (0.5, SPSub (SPFloor (singleval), singleval)) == 1)
- longval = (LONG) SPFix (SPFloor (singleval));
- else
- longval = (LONG) SPFix (SPCeil (singleval));
- break; /*if fnum-fix(fnum)<0.5 round_down else round_up */
- }
- sym = longconst;
- typ = longtype;
- }
- else if (ch == '!' || ch == '#')
- {
- /* coerce to a SINGLE constant */
- nextch ();
- switch (typ)
- {
- case shorttype:
- singleval = SPFlt ((LONG) shortval);
- break;
- case longtype:
- singleval = SPFlt (longval);
- break;
- }
- sym = singleconst;
- typ = singletype;
- }
- }
-
- void classify_integer (LONG n)
- {
- /* classify as a long or short integer value */
- if (n >= 0 && n <= MAXSHORT)
- {
- /* SHORT constant */
- shortval = (SHORT) n;
- sym = shortconst;
- typ = shorttype;
- }
- else
- {
- /* LONG constant */
- longval = n;
- sym = longconst;
- typ = longtype;
- }
- }
-
- void insymbol (void)
- /* lexical analyser */
- {
- int i, cc = 0;
- char ssym[3];
- LONG n[2], n0, n1;
- int index;
- int periods;
- BOOL period;
- LONG places;
- int placecount;
- /* int ex; no reference */
- LONG val;
- BYTE num;
- int sign;
- char lastch = ' ';
-
- lastsym = sym;
- sym = undefined;
- obj = undefined;
- typ = undefined;
-
- if (!end_of_source)
- {
- /* skip whitespace */
- while (ch <= ' ')
- {
- nextch ();
- if (end_of_source)
- return;
- if (sym == endofline)
- return; /* for PRINT */
- }
-
- /* single-line comment? */
- if (ch == '\'')
- {
- do
- {
- nextch ();
- }
- while ((sym != endofline) && (!end_of_source));
- if (end_of_source)
- return;
- if (sym == endofline)
- return; /* for PRINT '... */
- }
-
- /* block comment? */
- if (ch == '{')
- {
- do
- {
- nextch ();
- }
- while ((ch != '}') && (!end_of_source));
-
- if (!end_of_source)
- nextch (); /* character after "}" */
- else
- return;
-
- if (sym == endofline)
- return; /* for PRINT {..} */
-
- /* skip whitespace */
- while (ch <= ' ')
- {
- nextch ();
- if (end_of_source)
- return;
- if (sym == endofline)
- return; /* for PRINT {..} eoln */
- }
- }
-
- /* identifier or reserved word? */
- if (letter () || (ch == '_'))
- {
- do
- {
- ut_id[cc] = ut_ch; /* keep an "untouched" version
- (ie: upper/lower case)
- for DATA statements, library function searches
- and external functions */
- id[cc++] = ch;
- nextch ();
- }
- while ((letter () || digit () || (ch == '.') || (ch == '_')) &&
- (cc < MAXIDSIZE - 2));
-
- id[cc] = '\0';
- ut_id[cc] = '\0';
-
- /* is there a qualifier? %&$!# */
- if (qualifier ())
- {
- if (ch == '&')
- ch = '@';
- if (ch == '!')
- ch = '['; /* this is ONLY because a jsr SUB_name& or
- SUB_name! gives an error in A68K, whereas
- SUB_name@ and SUB_name[ don't!! */
- id[cc++] = ch;
- nextch ();
- }
-
- id[cc] = '\0';
- ut_id[cc] = '\0';
-
- /* reserved word? */
- if ((sym = rsvd_wd (id)) == undefined)
- {
- /* no, it's an identifier */
- convert_special_ident ();
-
- sym = ident;
-
- if (typ == undefined)
- {
- /*
- ** Data type = ASCII value of 1st char in id minus 'A'.
- ** Note that the underscore character is also catered
- ** for here since it is higher in the ASCII table than
- ** "Z". See lexvar.c, misc.c and setup() (above) for
- ** more info.
- */
- typ = idtype[id[0] - 'A'];
-
- obj = variable;
- }
- }
- else
- {
- /*
- ** It's a reserved word, so typ & obj mean nothing, but may
- ** have been set by qualifier() if qualifier character was a '$'
- */
- typ = undefined;
- obj = rsvd_word;
- }
- }
- else
- /* string constant? */
- if (ch == '"')
- {
- inside_string = TRUE;
- cc = 0;
- do
- {
- nextch ();
- stringval[cc++] = ch;
- }
- while ((ch != '"') && (ch != '\0') && (cc < MAXSTRLEN));
- if (ch == '"')
- --cc;
- if (ch == '"')
- nextch ();
- stringval[cc] = '\0';
- sym = stringconst;
- typ = stringtype;
- obj = constant;
- inside_string = FALSE;
- }
- else
- /* numeric literal? */
- if (digit () || (ch == '.'))
- {
- n[0] = n[1] = 0;
- index = 0;
- period = FALSE;
- periods = 0;
- placecount = 0;
-
- /* is first char '.'? */
- if (ch == '.')
- {
- period = TRUE;
- placecount = 0;
- index = 1;
- periods++;
- }
- /* get the value */
- if (!period)
- n[0] = 10 * n[0] + (ch - '0');
- do
- {
- nextch ();
- if (digit ())
- n[index] = 10 * n[index] + (ch - '0');
- if (digit () && period)
- placecount++;
- if (ch == '.')
- periods++;
- if ((ch == '.') && (!period))
- {
- period = TRUE;
- placecount = 0;
- index = 1;
- }
- }
- while ((digit () || ch == '.') && (periods <= 1));
-
- /* integer or real? */
- if (period && (periods == 1))
- {
- /* make FFP */
- sym = singleconst;
- typ = singletype;
- places = 1;
- for (i = 1; i <= placecount; i++)
- places *= 10;
- n0 = n[0];
- n1 = n[1];
- singleval = SPAdd (SPFlt (n0), SPDiv (SPFlt (places), SPFlt (n1)));
-
- /* printf("%lx\n",singleval); original */
- /* printf("%x\n",singleval); */
- /* char ffpbuf[20];
- ex = fpa(singleval,ffpbuf);
- printf("%f\n",singleval);
- ffpbuf[14]='\0';
- printf("FFP: %s\t%lx\t",ffpbuf,singleval);
- ffprint(ex,ffpbuf); */
- }
- else
- classify_integer (n[0]);
-
- reclassify_number ();
-
- /* is it a real in scientific format? */
- if ((ch == 'e') || (ch == 'E'))
- {
- long ex = 0;
- sign = 1;
- nextch ();
- if (ch == '+')
- {
- sign = 1;
- nextch ();
- }
- else if (ch == '-')
- {
- sign = -1;
- nextch ();
- }
- if (!digit ())
- _error (3); /* expect a digit */
- /* get digits */
- while (digit ())
- {
- ex = 10 * ex + (ch - 48);
- nextch ();
- }
- ex *= sign;
- /* convert to FFP */
- if ((ex >= -20) && (ex <= 18))
- {
-
- /* mantissa */
- if (sym != singleconst)
- {
- singleval = SPFlt (n[0]);
- sym = singleconst;
- typ = singletype;
- }
-
- /* if exponent is zero: 10^ex = 1 -> num*1 = num
- so just return singleval as it is. */
- if (ex != 0)
- singleval = SPMul (SPPow (SPFlt (ex), 10.0), singleval);
-
- reclassify_number ();
- }
- else
- {
- singleval = 0.0;
- _warn (1);
- }
- }
- obj = constant;
- }
- else
- /* reserved symbol? */
- if (ch == '\\') /* backslash */
- {
- sym = idiv;
- nextch ();
- }
- else if (ssymbol () || (ch == '&') || (ch == '#'))
- {
- /* one character symbol? */
- ssym[0] = ch;
- ssym[1] = '\0';
- sym = rsvd_sym (ssym); /* tentatively */
-
- lastch = ch; /* might be '&' or '*' */
- nextch ();
-
- /* multiple character symbol? (++,--,->,<>,<=,>=,:=,&H,&O,*%,*&,*!) */
-
- /* ++ */
- if (sym == plus && ch == '+')
- {
- ssym[1] = ch;
- ssym[2] = '\0';
- sym = rsvd_sym (ssym);
- nextch ();
- }
- else
- /* --,-> */
- if (sym == minus && (ch == '-' || ch == '>'))
- {
- ssym[1] = ch;
- ssym[2] = '\0';
- sym = rsvd_sym (ssym);
- nextch ();
- }
- else
- /* <>,<= */
- if (sym == lessthan && (ch == '>' || ch == '='))
- {
- ssym[1] = ch;
- ssym[2] = '\0';
- sym = rsvd_sym (ssym);
- nextch ();
- }
- else
- /* >=,:= */
- if ((sym == gtrthan || sym == colon) && ch == '=')
- {
- ssym[1] = ch;
- ssym[2] = '\0';
- sym = rsvd_sym (ssym);
- nextch ();
- }
- else
- /* &H,&O */
- if (lastch == '&' && (ch == 'H' || ch == 'O'))
- {
- ssym[1] = ch;
- ssym[2] = '\0';
- sym = rsvd_sym (ssym);
- nextch ();
- }
- else
- /* *%,*&,*! */
- if (lastch == '*' && (ch == '%' || ch == '&' || ch == '!'))
- {
- ssym[1] = ch;
- ssym[2] = '\0';
- sym = rsvd_sym (ssym);
- nextch ();
- }
-
-
- /* hexadecimal constant? */
- if (sym == hexprefix)
- {
- val = 0;
- if (hex_digit () == -1)
- _error (2);
- else
- while ((num = hex_digit ()) != -1)
- {
- val = 16 * val + num;
- nextch ();
- }
- classify_integer (val);
- reclassify_number ();
- }
- else
- /* octal constant? */
- if ((sym == octalprefix) || ((ssym[0] == '&') && (strlen (ssym) == 1)))
- {
- val = 0;
- if (octal_digit () == -1)
- _error (2);
- else
- {
- while ((num = octal_digit ()) != -1)
- {
- val = 8 * val + num;
- nextch ();
- }
- classify_integer (val);
- reclassify_number ();
- }
- }
- }
- /*
- ** Unknown symbol.
- */
- if (sym == undefined)
- {
- _error (2);
- nextch ();
- }
- /*showsym(sym); lf(); */
- }
- }
-
- /*
- void showsym(int sym)
- {
- if (sym == undefined) printf("undefined");
- else
- if (sym <= RWSENTINEL) printf("%s -> %d",rword[sym],sym);
- else
- if (sym <= RSSENTINEL) printf("%s",rsym[sym-500]);
- else
- printf("%s",symbol[sym-1000]);
- }
-
- void showobj(int obj)
- {
- if (obj == undefined) printf(" undefined");
- else
- printf("%10s",object[obj-3000]);
- }
-
- void showtyp(int typ)
- {
- if (typ == undefined) printf(" undefined");
- else
- printf("%10s",type[typ-2000]);
- }
-
- void tab(void)
- {
- putchar('\t');
- }
-
- void lf(void)
- {
- putchar('\n');
- }
- */
-
- /*
- void main(int argc,char *argv[])
- {
- if (argc == 1) { src = stdin; std_in=TRUE; }
- else
- open_files(argv[1]);
- setup();
- while (!end_of_source)
- {
- insymbol();
- puts(" ");
- showsym(sym); tab();
- showobj(obj); tab();
- showtyp(typ); lf();
- switch(sym)
- {
- case stringconst : printf("-->>%s\n",stringval); break;
- case shortconst : printf("-->>%d\n",shortval); break;
- case longconst : printf("-->>%ld\n",longval); break;
- case singleconst : printf("-->>%x\n",singleval); break;
- }
- }
- cleanup();
- }
- */
-